// @Author yang
// @Description 
// @Date 2022/1/7
// @Time 11:19

package aop

import (
	"fmt"
	"math"
)

const ABORT = math.MaxInt32 - 10000

type Context struct {
	offset   int
	handers  []func(*Context) (res interface{}, err error)
	mdiwares []func(*Context) (res interface{}, err error)
}

func newContext() *Context {
	return &Context{
		offset:   -1,
		handers:  make([]func(ctx *Context) (res interface{}, err error), 0, 10),
		mdiwares: make([]func(ctx *Context) (res interface{}, err error), 0, 10),
	}
}

func (ctx *Context) Next() (res interface{}, err error) {
	ctx.offset++
	s := len(ctx.handers)

	if ctx.isAbort() {
		return nil, fmt.Errorf("handers aborted!")
	}

	for ; ctx.offset < s; ctx.offset++ {
		if !ctx.isAbort() {
			res, err = ctx.handers[ctx.offset](ctx)
			if err != nil {
				return nil,err
			}
		} else {
			return nil, fmt.Errorf("handers aborted!")
		}
	}
	return res, err
}

func (ctx *Context) Reset() {
	ctx.offset = -1
	ctx.handers = ctx.handers[:0]
}

func (ctx *Context) isAbort() bool {
	if ctx.offset >= ABORT {
		return true
	}
	return false
}

func (ctx *Context) Abort() () {
	ctx.offset = ABORT
}

func (ctx *Context) addHanders(fs ...func(ctx *Context)(interface{}, error)) () {
	ctx.handers = append(ctx.handers, fs...)
}

func (ctx *Context) addMidwares(fs ...func(ctx *Context)(interface{}, error)) () {
	ctx.mdiwares = append(ctx.mdiwares, fs...)
}
